

#ifndef RENDERSTATE_H
#define RENDERSTATE_H

#include "typedefs.h"
#include <map>

#include <eq/eq.h>
#include "channel.h"


namespace pc 
{
    /*  The abstract base class for kd-tree rendering state.  */
    class RenderState
    {
    public:
        enum
        {
            INVALID = 0 //<! return value for failed operations.
        };

        virtual bool useColors() const { return _useColors; }
        virtual void setColors( const bool colors ) { _useColors = colors; }
        virtual bool stopRendering() const { return false; }
        virtual RenderMode getRenderMode() const { return _renderMode; }
        virtual void setRenderMode( const RenderMode mode );
        virtual bool useFrustumCulling() const { return _useFrustumCulling; }
        virtual void setFrustumCulling( const bool frustumCullingState )
            { _useFrustumCulling = frustumCullingState; }

        void setProjectionModelViewMatrix( const Matrix4f& pmv )
            { _pmvMatrix = pmv; }
        const Matrix4f& getProjectionModelViewMatrix() const
            { return _pmvMatrix; }

        void setRange( const Range& range ) { _range = range; }
        const Range& getRange() const { return _range; }

        void resetRegion();
        void updateRegion( const BoundingBox& box );
        virtual void declareRegion( const Vector4f& region ) {}
        Vector4f getRegion() const;

        virtual GLuint getDisplayList( const void* key ) = 0;
        virtual GLuint newDisplayList( const void* key ) = 0;
        virtual GLuint getBufferObject( const void* key ) = 0;
        virtual GLuint newBufferObject( const void* key ) = 0;
        virtual void deleteAll() = 0;

        const GLEWContext* glewGetContext() const { return _glewContext; }
        
    protected:
        RenderState( const GLEWContext* glewContext );        
        virtual ~RenderState() {}
        
        Matrix4f      _pmvMatrix; //!< projection * modelView matrix
        Range         _range; //!< normalized [0,1] part of the model to draw
        const GLEWContext* const _glewContext;
        RenderMode    _renderMode;
        Vector4f      _region; //!< normalized x1 y1 x2 y2 region from cullDraw 
        bool          _useColors;
        bool          _useFrustumCulling;
        
    private:
    };
    
    
    /*  Simple state for stand-alone single-pipe usage.  */
    class RenderStateSimple : public RenderState 
    {
    private:
        typedef std::map< const void*, GLuint > GLMap;
        typedef GLMap::const_iterator GLMapCIter;

    public:
        RenderStateSimple( const GLEWContext* glewContext )
            : RenderState( glewContext ) {}
        
        virtual GLuint getDisplayList( const void* key );
        virtual GLuint newDisplayList( const void* key );        
        virtual GLuint getBufferObject( const void* key );        
        virtual GLuint newBufferObject( const void* key );
        virtual void deleteAll();

    private:
        GLMap  _displayLists;
        GLMap  _bufferObjects;
    };
} // namespace pc


namespace eqPc
{
    /*  State for Equalizer usage, uses Eq's Object Manager.  */
    class RenderState : public pc::RenderState 
    {
    public:
        RenderState( eq::Window::ObjectManager* objectManager ) 
                : pc::RenderState( objectManager->glewGetContext( ))
                , _objectManager( objectManager )
            {} 
        
        virtual GLuint getDisplayList( const void* key )
            { return _objectManager->getList( key ); }
        
        virtual GLuint newDisplayList( const void* key )
            { return _objectManager->newList( key ); }
        
        virtual GLuint getTexture( const void* key )
            { return _objectManager->getTexture( key ); }
        
        virtual GLuint newTexture( const void* key )
            { return _objectManager->newTexture( key ); }
        
        virtual GLuint getBufferObject( const void* key )
            { return _objectManager->getBuffer( key ); }
        
        virtual GLuint newBufferObject( const void* key )
            { return _objectManager->newBuffer( key ); }
        
        virtual GLuint getProgram( const void* key )
            { return _objectManager->getProgram( key ); }
        
        virtual GLuint newProgram( const void* key )
            { return _objectManager->newProgram( key ); }
        
        virtual GLuint getShader( const void* key )
            { return _objectManager->getShader( key ); }
        
        virtual GLuint newShader( const void* key, GLenum type )
            { return _objectManager->newShader( key, type ); }

        virtual void deleteAll() { _objectManager->deleteAll(); }

        bool isShared() const { return _objectManager->isShared(); }
        
        void setChannel( Channel* channel ) { _channel = channel; }

        virtual bool stopRendering( ) const
            { return _channel ? _channel->stopRendering() : false; }

        virtual void declareRegion( const pc::Vector4f& region ) 
            { if( _channel ) _channel->declareRegion( eq::Viewport( region )); }

    private:
        eq::Window::ObjectManager* _objectManager;
        Channel* _channel;
    };
} // namespace eqPly

    

#endif // MESH_VERTEXBUFFERSTATE_H
